{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Programming On Linux\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1 The software for programming C/C++ and  Python on Linux\n",
    "\n",
    "### 1.1 C/C++\n",
    "\n",
    "* ❑ GCC: The GNU Compiler Collection, containing the GNU C compiler\n",
    "\n",
    "* ❑ G++: A C++ compiler, included as part of GCC\n",
    "\n",
    "* ❑ GNU make: A version of UNIX make\n",
    "\n",
    "Most Linux distributions, such as Ubuntu, have built-in GCC compilers and do not require additional installation\n",
    "\n",
    "\n",
    "If you use the Debian/Ubuntu distribution do not has built-in GCC compilers. you can install the folloing command\n",
    " \n",
    "```bash \n",
    "$sudo apt install build-essential\n",
    "```\n",
    "\n",
    "The command installs a bunch of new packages including gcc, g++ and make.\n",
    "\n",
    "### 1.2 Python\n",
    "\n",
    "All Linux distributions have built-in Python2 and Python2. However, it is incomplete\n",
    "\n",
    "* Add 3 to the relevant commands of Python3\n",
    "\n",
    "\n",
    "For Python3, we need to be supplemented with `pip3` and `idle3`.\n",
    "\n",
    "```bash\n",
    "$sudo apt install python3-pip\n",
    "$sudo apt install idle3\n",
    "```\n",
    "\n",
    "**Install Python3 packages:**\n",
    "\n",
    "\n",
    "* set `tsinghua` as the mirror site of Pypi\n",
    "\n",
    "```bash\n",
    "$sudo -H python3 -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n",
    "```\n",
    "* upgrade pip3\n",
    "\n",
    "```bash\n",
    "$sudo -H python3 -m  pip install pip -U\n",
    "```\n",
    "* Installing Packages\n",
    "\n",
    "```bash\n",
    "$sudo -H python3 -m pip install jupyter \n",
    "```\n",
    "\n",
    "```bash\n",
    "$sudo -H  python3 -m pip install coolprop \n",
    "```\n",
    "\n",
    "### 1.3 The text editor and programming environment\n",
    "\n",
    "**Visual Studio Code**\n",
    "\n",
    "From  https://code.visualstudio.com/docs/?dv=linux64_deb  download VS Code for Debian/Ubuntu,\n",
    "\n",
    "then install in the terminal\n",
    "\n",
    "```bash\n",
    "$sudo dpkg -i [vscode filename].deb\n",
    "```\n",
    "\n",
    "### 1.4 Version Control:Git\n",
    "\n",
    "```bash \n",
    "$sudo apt install git\n",
    "```\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "   \n",
    "## 2 C/C++\n",
    "\n",
    "The working directory: `PySEE/home/notebook/demo`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/mnt/j/SEU/SEE/PySEE/home/notebook/demo\n"
     ]
    }
   ],
   "source": [
    "%cd demo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'/mnt/j/SEU/SEE/PySEE/home/notebook/demo'"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.1 Bisection Methond in C\n",
    "\n",
    "𝑦=𝑓(𝑥) \n",
    "\n",
    "* ./include/roots.h\n",
    "\n",
    "* ./src/roots.c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %load ./include/roots.h\n",
    "#ifndef ROOTS_H\n",
    "#define ROOTS_H\n",
    "\n",
    "#include <math.h>\n",
    "// function definition\n",
    "typedef double (*fun)(double);\n",
    "\n",
    "int rtbis(fun func,double y,double x1, double x2, double xacc,double *rtb);\n",
    "/*\n",
    "\tThe program uses the bisection method to solve the equation\n",
    "\t\tf(x)-y = 0.\n",
    "\tThe solution is to be in [x1,x2] and it is assumed that\n",
    "\t\t(f(x1)-y)*(f(x2)-y) <= 0.\n",
    "\tThe solution is returned in rtb, and it is to be in error by at most xacc.\n",
    "\t\n",
    "\treturn value is an error indicator.\n",
    "\t  If =0, the solution has been computed satisfactorily.\n",
    "\t  If =1, (f(x1)-y)*(f(x2)-y) was greater than 0, contrary to assumption \n",
    "      If =2, exceeded the maximum number of iteration \n",
    "*/\n",
    "#endif\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %load ./src/roots.c\n",
    "/*\n",
    "  Numerical Recipes http://numerical.recipes\n",
    "*/ \n",
    "#include <math.h>\n",
    "#include \"roots.h\"\n",
    "\n",
    "int rtbis(fun func,double y,double x1, double x2, double xacc,double *rtb)\n",
    "{\n",
    " /*\n",
    "\tThe program uses the bisection method to solve the equation\n",
    "\t\tf(x)-y = 0.\n",
    "\tThe solution is to be in [x1,x2] and it is assumed that\n",
    "\t\t(f(x1)-y)*(f(x2)-y) <= 0.\n",
    "\tThe solution is returned in rtb, and it is to be in error by at most xacc.\n",
    "\t\n",
    "\treturn value is an error indicator.\n",
    "\t  If =0, the solution has been computed satisfactorily.\n",
    "\t  If =1, (f(x1)-y)*(f(x2)-y) was greater than 0, contrary to assumption \n",
    "      If =2, exceeded the maximum number of iteration \n",
    "*/\n",
    "\tconst int IMAX=100; // the maximum number of iteration\n",
    "    float dx,f,fmid,xmid;\n",
    "\n",
    "\tf=(*func)(x1)-y;\n",
    "\tfmid=(*func)(x2)-y;\n",
    "\tif (f*fmid >= 0.0) // endpoints do not straddle y=0\n",
    "       return 1; \n",
    "    // init the root value: rtb\n",
    "\t*rtb = f < 0.0 ? (dx=x2-x1,x1) : (dx=x1-x2,x2);\n",
    "\tfor (int i=1;i<=IMAX;i++) {\n",
    "\t\tfmid=(*func)(xmid=(*rtb)+(dx *= 0.5))-y;\n",
    "\t\tif (fmid <= 0.0) *rtb=xmid;\n",
    "\t\tif (fabs(dx) < xacc || fmid == 0.0) \n",
    "           return 0;\n",
    "  \t}\n",
    "    // Exceeded the maximum number of iteration\n",
    "    return 2;\n",
    "}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.2 The caller of Bisection Methond \n",
    "\n",
    "$𝑓(𝑥)=𝑥2$ \n",
    "\n",
    "$4=𝑓(𝑥)$\n",
    "\n",
    "```c\n",
    "int rtbis(fun func,double y,double x1, double x2, double xacc,double *rtb)\n",
    "\n",
    "double xl, xu, epsilon, root;\n",
    "ier=rtbis(fcn,y,xl, xu, epsilon, &root);\n",
    "```\n",
    "&root > double *rtb"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# %load ./src/rtbisApp.c\n",
    "\n",
    "#include <stdio.h>\n",
    "#include <string.h>\n",
    "#include <stdlib.h>\n",
    "#include \"roots.h\"\n",
    "\n",
    "double fcn(double x)\n",
    "{\n",
    "\tdouble result;\n",
    "\tresult = x * x;\n",
    "\treturn result;\n",
    "}\n",
    "\n",
    "int main()\n",
    "{\n",
    "\tdouble xl, xu, epsilon, root;\n",
    "\tint ier;\n",
    "\txl = 0.1;\n",
    "\txu = 3.2;\n",
    "\tepsilon = 0.001;\n",
    "    double y=4;\n",
    "\t// Calculate root\n",
    "\tier=rtbis(fcn,y,xl, xu, epsilon, &root);\n",
    "\t// Print answers\n",
    "\tprintf(\"root = %14.7e  ier = %1d\", root, ier);\n",
    "\treturn 0;\n",
    "}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o ./bin/rtbisApp ./src/rtbisApp.c  ./src/roots.c -I./include/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!./bin/rtbisApp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Further Reading:**\n",
    "\n",
    "**Path separators**\n",
    "\n",
    "* Linux: /\n",
    "\n",
    "* Windows: \\\n",
    "\n",
    "Escape character \\\n",
    "\n",
    "* The backslash`\\` is an escape character,you use to inform that the next character is special."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "### 2.3 The shared library\n",
    "\n",
    "Linux supports two classes of libraries, namely:\n",
    "\n",
    "* Static libraries – are bound to a program statically at compile time. \n",
    "* Shared libraries – are loaded when a program is launched and loaded into memory and binding occurs at run time. \n",
    "\n",
    "GCC assumes that all libraries on Linux\n",
    "\n",
    "* start with `lib`\n",
    "\n",
    "* Static libraries : end with `.a`\n",
    "\n",
    "* Shared libraries: end with `.so`\n",
    "\n",
    "\n",
    "#### 2.3.1 creating the shared  library\n",
    "\n",
    "using `__cdecl` calling convention"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -c -O3 -Wall -fPIC -o ./obj/roots.o  ./src/roots.c -I./include\n",
    "!gcc -shared -o ./bin/libroots.so  ./obj/roots.o"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rwxrwxrwx 1 cmh cmh 15736 Jan 10 09:30 ./bin/libroots.so\r\n"
     ]
    }
   ],
   "source": [
    "!ls -l ./bin/lib*.so"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.3.2 Using the shared library\n",
    "\n",
    "We use the same code `./src/statdemo.c` under Windows\n",
    "\n",
    "**Linking the library**\n",
    "\n",
    "**Windows**\n",
    "```bash\n",
    "    -L./bin/ -lstat\n",
    "```\n",
    "**Linux**\n",
    "```bash\n",
    "   -L./bin/ -lstat -Wl,-rpath=./bin/  \n",
    "```\n",
    "* **`-Wl,option`**\n",
    "\n",
    "    Pass option as an option to the **linker**. \n",
    "    \n",
    "    If option contains `commas`, it is split into multiple options at the commas. \n",
    "    \n",
    "    You can use this syntax to pass an argument to the option.\n",
    "      \n",
    "   \n",
    "* **`-rpath=dir`** \n",
    "\n",
    "   **Add a directory to the `runtime` library search path**. This is used when linking an executable with shared objects. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o  ./bin/rtbisApp ./src/rtbisApp.c -L./bin/ -lroots -I./include -Wl,-rpath=./bin/ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "root =  1.9996581e+00  ier = 0"
     ]
    }
   ],
   "source": [
    "!./bin/rtbisApp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2.4  The standard search  Path of library and header files\n",
    "\n",
    "#### 2.4.1 The standard search  Path of library \n",
    "There are mainly standard locations in the filesystem where a library can be placed.\n",
    "\n",
    "* `/lib`, `/lib64`:   system startup libraries\n",
    "* `/usr/lib`,`/usr/lib64`\n",
    "* `/usr/local/lib`, `/usr/local/lib64`\n",
    "\n",
    "These directory are the standard search paths of GCC linker, if your library is installed in its default location, GCC searches it automatically, so the `-L` option can be omitted \n",
    "\n",
    "#### 2.4.2 The standard search  Path of header \n",
    "There are mainly standard locations in the filesystem where a header file can be placed.\n",
    "\n",
    "* `/usr/include`\n",
    "\n",
    "These directory are the standard search paths of GCC compiler, if your header files are installed in its default location, GCC searches it automatically so the `-I` option can actually be omitted\n",
    "\n",
    "#### 2.4.3 Using  the standard search paths\n",
    "\n",
    "#####  Put your files into  the standard search paths\n",
    "\n",
    "Copy your header files and library to the the standard search paths of GCC\n",
    "\n",
    "```\n",
    "$sudo cp ./include/roots.h /usr/include/roots.h\n",
    "$sudo cp ./bin/libroots.so /usr/lib/libroots.so\n",
    "\n",
    "```\n",
    "\n",
    "![](./img/linux/copy2searchpath.jpg)\n",
    "\n",
    ">`cp` is a command used for copying files and directories in Linux\n",
    ">\n",
    ">`cp [options] source dest`\n",
    ">\n",
    "> -f : force to do,if you don't want to be bothered by prompts or don't care about errors, use the force\n",
    ">\n",
    ">  * `cp -f` : overlay the existing target file without prompting"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rwxr-xr-x 1 root root 15736 Jan 10 09:46 /usr/lib/libroots.so\r\n"
     ]
    }
   ],
   "source": [
    " !ls -l  /usr/lib/libroots.so"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "-rwxr-xr-x 1 root root 677 Jan 10 09:49 /usr/include/roots.h\r\n"
     ]
    }
   ],
   "source": [
    "!ls -l /usr/include/roots.h"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##### Compiling ad linker without `-I` and `-L`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "root =  1.9996581e+00  ier = 0"
     ]
    }
   ],
   "source": [
    "!gcc -o  ./bin/rtbisApp ./src/rtbisApp.c -L./bin/ -lroots \n",
    "!./bin/rtbisApp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Delete these files from these default search path**\n",
    "```bash\n",
    "$sudo rm -f /usr/include/roots.h\n",
    "$sudo rm -f /usr/lib/libroots.so\n",
    "```\n",
    ">`rm` is a command-line utility for removing files and directories\n",
    ">\n",
    ">rm [options] name...\n",
    ">\n",
    "> `rm -f`: will forcibly delete files without asking"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ls: cannot access '/usr/lib/libroots.so': No such file or directory\r\n"
     ]
    }
   ],
   "source": [
    "!ls -l  /usr/lib/libroots.so"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ls: cannot access '/usr/include/roots.h': No such file or directory\r\n"
     ]
    }
   ],
   "source": [
    "!ls -l /usr/include/roots.h"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\u001b[01m\u001b[K./src/rtbisApp.c:5:10:\u001b[m\u001b[K \u001b[01;31m\u001b[Kfatal error: \u001b[m\u001b[Kroots.h: No such file or directory\r\n",
      "    5 | #include \u001b[01;31m\u001b[K\"roots.h\"\u001b[m\u001b[K\r\n",
      "      |          \u001b[01;31m\u001b[K^~~~~~~~~\u001b[m\u001b[K\r\n",
      "compilation terminated.\r\n"
     ]
    }
   ],
   "source": [
    "!gcc -o  ./bin/rtbisApp ./src/rtbisApp.c -L./bin/ -lroots"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o  ./bin/rtbisApp ./src/rtbisApp.c -L./bin/ -lroots -I./include -Wl,-rpath=./bin/ "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "root =  1.9996581e+00  ier = 0"
     ]
    }
   ],
   "source": [
    "!./bin/rtbisApp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 2.4.5 makefile\n",
    "```bash\n",
    "sudo make -f maketosyspath.mk\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./maketosyspath.mk\n"
     ]
    }
   ],
   "source": [
    "%%file ./maketosyspath.mk\n",
    "BIN=./bin/\n",
    "SRC=./src/\n",
    "OBJ=./obj/\n",
    "INC=./include/\n",
    "\n",
    "all: makeso syspath\n",
    "\n",
    "syspath:   \n",
    "\tsudo cp $(INC)roots.h /usr/include/roots.h\n",
    "\tsudo cp $(BIN)libroots.so /usr/lib/libroots.so      \n",
    "makeso:\n",
    "\tgcc -c -O3 -Wall -fPIC -o $(OBJ)roots.o  $(SRC)roots.c -I$(INC)\n",
    "\tgcc -shared -o $(BIN)libroots.so  $(OBJ)roots.o\n",
    "\n",
    "clean:\n",
    "\tsudo rm -f /usr/include/roots.h\n",
    "\tsudo rm -f /usr/lib/libroots.so    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "root =  1.9996581e+00  ier = 0"
     ]
    }
   ],
   "source": [
    "!gcc -o  ./bin/rtbisApp ./src/rtbisApp.c -L./bin/ -lroots \n",
    "!./bin/rtbisApp"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```bash\n",
    "sudo make -f maketosyspath.mk clean\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [],
   "source": [
    "!gcc -o  ./bin/rtbisApp ./src/rtbisApp.c -L./bin/ -lroots -I./include -Wl,-rpath=./bin/ "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3 Using The CoolProp Shared Library\n",
    "\n",
    "**Change working dir to `./notebook/coolpropdemo`**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "/mnt/j/SEU/SEE/PySEE/home/notebook/coolpropdemo\n"
     ]
    }
   ],
   "source": [
    "%cd ./coolpropdemo"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%pwd"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 Managing Linux Shared Libraries\n",
    "\n",
    "In Linux you can have **different versions** of the same shared library in the same system.\n",
    "\n",
    "* This allows you to add a newer version of the shared library which is `not compatible` with the older library interface **without breaking** the functionality of binaries which use the older library. \n",
    "\n",
    "* The programs linking with the shared library **do not need to take care** about the latest version of the shared library installed in the system. Once the latest version of the shared library is installed successfully, all the programs automatically start linking to the latest version.1111\n",
    "\n",
    "#### 3.1.1 Shared libraries Name on Linux\n",
    "\n",
    "\n",
    "**soname**\n",
    "\n",
    "Every shared library has a special name called the `soname(Short for shared object name）`. The soname has the prefix `lib`, the name of the library, the phrase `.so` followed by a version number \n",
    "\n",
    "The soname is used to indicate what binary **api compatibility** your library support by providing version **backwards-compatibility** information. For instance, if version 6.0.0 through 6.4.1 of the shared library `libCoolProp` provide identical interfaces, they all have the same soname, `libCoolProp.so.6` \n",
    "\n",
    "On a working system. a fully-qualified soname is simply `a symbolic link` to the shared library's `real name`.\n",
    "\n",
    "The symlink is what programs using the library will look for, the running programs do not care about the **version number.**\n",
    "\n",
    ">using `soname` to manage the version : `-Wl,-soname,`$(SONAME)`\n",
    ">\n",
    ">gcc -shared -fPIC -o `$(REAL_NAME)` foo.c -Wl,-soname,`$(SONAME)`\n",
    ">\n",
    "\n",
    "**real name**\n",
    "\n",
    "Every shared library also has a `real name`, which is the filename containing the actual library code. The real name adds to the soname a  minor number and the release number. \n",
    "\n",
    "**linker name**\n",
    "\n",
    "linker name is the name that the compiler uses when requesting a library, which is simply the soname **without any version number**\n",
    "\n",
    "The linker name is simply created as `a symbolic link to the soname` \n",
    "\n",
    "The symlink is what programs using the library will look for, the running programs do not care about the **version number**\n",
    "\n",
    "> **A symbolic link** is a `file` that links to another file or directory using its path. you can think of a symbolic link as `a shortcut` to a file or directory (folder). symbolic links may be used in the command line, or in a script or another program.\n",
    "\n",
    "These naming conventions help **multiple** versions of same shared library to **co-exist** in a system.\n",
    "\n",
    "\n",
    "\n",
    "The name used by linker is usually a symbolic link to the fully qualified soname which in turn is a symbolic link to the real name.\n",
    "\n",
    "* `linker name(a symbolic link) > soname(a symbolic link) > real name`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.1.2 The CoolProp Shared Library use soname to manage the version\n",
    "\n",
    "* `libCoolProp.so.6.4.1` is the library using soname to manage the version\n",
    "\n",
    "  * `libCoolProp.so.6.4.1` is **real name**\n",
    "\n",
    "* `libCoolProp.so.6` is **soname**,version 6\n",
    "\n",
    "* `libCoolProp` is **linker name**\n",
    "\n",
    "\n",
    "To find the soname of the library run:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!readelf -a ./bin/libCoolProp.so.6.4.1 | grep SONAME"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "**readelf  - Displays information about ELF files.**\n",
    "\n",
    "\n",
    "* `-a`: quivalent to specifying --file-header, --program-headers, --sections, --symbols, --relocs, --dynamic, --notes and --version-info.\n",
    "\n",
    "**ELF**\n",
    "\n",
    "\n",
    "ELF is the abbreviation for ·Executable and Linkable Format· and defines the structure for binaries, libraries, and core files. \n",
    "\n",
    "The formal specification allows the operating system to interpreter its underlying machine instructions correctly. \n",
    "\n",
    "ELF files are typically the output of a compiler or linker and are a binary format.\n",
    "\n",
    "**Grep**\n",
    "\n",
    "Grep is an acronym that stands for `Global Regular Expression Print`. \n",
    "\n",
    "Grep is a Linux/Unix command-line tool used to search for `a string of characters` in a specified file. \n",
    "\n",
    "The `text search pattern` is called a regular expression.\n",
    "\n",
    "When it finds a match, it prints the line with the result\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**The pipe character ‘|’**\n",
    "\n",
    "A pipe is a form of `redirection` (transfer of standard output to some other destination) that is used in Linux and other Unix-like operating systems to send the output of one command/program/process to another command/program/process for further processing. \n",
    "\n",
    "The Unix/Linux systems allow stdout of a command to be connected to stdin of another command. You can make it do so by using `the pipe character ‘|’`.\n",
    "\n",
    "Syntax :\n",
    "\n",
    "`command_1 | command_2 | command_3 | .... | command_N `\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.1.3 Install the CoolProp to the default path on Linux\n",
    "\n",
    "copy  `./bin/libCoolProp.so.6.4.1` to  the default path `/usr/lib`\n",
    "\n",
    "```bash\n",
    "$sudo cp ./bin/libCoolProp.so.6.4.1 /usr/lib/\n",
    "```\n",
    "\n",
    "type the following command in the terminal of `./coolpropdemo/` to create the symbolic link `libCoolProp.so.6` and `libCoolProp.so`\n",
    "```bash\n",
    "$sudo ln -sf libCoolProp.so.6.4.1  /usr/lib/libCoolProp.so.6\n",
    "$sudo ln -sf libCoolProp.so.6  /usr/lib/libCoolProp.so\n",
    "```\n",
    "\n",
    "![installcoolprop2linux](./img/linux/installcoolprop2linux.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The soname `libCoolProp.so.6`  is a symlink which points to the real name(actual library) `libCoolProp.so.6.4.1`. \n",
    "\n",
    "The linker name `libCoolProp.so`  is a symlink which points to the soname `libCoolProp.so.6` "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "**`ln`** is a command-line utility for creating **links** between files.\n",
    "\n",
    "To create a symbolic link to a given file, use the `-s (--symbolic)` option.\n",
    "\n",
    "```bash\n",
    " $ln -s source_file symbolic_link\n",
    "```\n",
    "\n",
    "`ln` with `-f` force option:  remove existing destination files\n",
    "\n",
    "```bash\n",
    "$ln -sf source_file symbolic_link\n",
    "```\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2 Using The CoolProp  shared library\n",
    "\n",
    "The CoolProp shared library in the default path `/usr/lib` "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./mainso.c\n"
     ]
    }
   ],
   "source": [
    "%%file ./mainso.c\n",
    "/* \n",
    "The example use the shared library of CoolProp in c\n",
    "\n",
    "g++ -DCOOLPROP_LIB  -o ./bin/mainso  mainso.c -I./include -L./bin -lCoolProp \n",
    "       \n",
    "./bin/mainso\n",
    "\n",
    "*/\n",
    "\n",
    "#include \"CoolPropLib.h\"\n",
    "#include <stdio.h>\n",
    "\n",
    "int main() {\n",
    "     double value=PropsSI(\"P\",\"T\",273.15+0,\"Q\",0,\"R134a\");\n",
    "     printf(\"%f\\n\", value); \n",
    "     return 0;\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "!g++ -DCOOLPROP_LIB -o ./bin/mainso  mainso.c -I./include -L./bin -lCoolProp "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "292803.182339\r\n"
     ]
    }
   ],
   "source": [
    "!./bin/mainso"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**MakeFile**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Overwriting ./makefile\n"
     ]
    }
   ],
   "source": [
    "%%file ./makefile\n",
    "BIN=./bin/\n",
    "INC=./include/\n",
    "MAIN_FILE=mainso.c\n",
    "SONAME=libCoolProp.so.6\n",
    "REAL_NAME=libCoolProp.so.6.4.1\n",
    "LINKER_NAME=libCoolProp.so\n",
    "OUTPUT_FILE=mainso.out\n",
    "LINKERFLAGS=-L./bin -lCoolProp \n",
    "\n",
    "all:buildexec exec\n",
    "\n",
    "buildexec:\n",
    "\tg++ -DCOOLPROP_LIB -o $(BIN)${OUTPUT_FILE}  $(MAIN_FILE) -I$(INC) $(LINKERFLAGS)\n",
    "    \n",
    "exec:\n",
    "\t$(BIN)${OUTPUT_FILE}\n",
    "    \n",
    "install:\n",
    "\tcp $(BIN)$(REAL_NAME) /usr/lib/\n",
    "\tln -sf $(REAL_NAME)  /usr/lib/$(SONAME)\n",
    "\tln -sf $(SONAME)  /usr/lib/$(LINKER_NAME)\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "g++ -DCOOLPROP_LIB -o ./bin/mainso.out  mainso.c -I./include/ -L./bin -lCoolProp \n",
      "./bin/mainso.out\n",
      "292803.182339\n"
     ]
    }
   ],
   "source": [
    "!make"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "g++ -DCOOLPROP_LIB -o ./bin/mainso.out  mainso.c -I./include/ -L./bin -lCoolProp \r\n"
     ]
    }
   ],
   "source": [
    "!make buildexec"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "./bin/mainso.out\n",
      "292803.182339\n"
     ]
    }
   ],
   "source": [
    "!make exec"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**install the coolprop  to linux**\n",
    "\n",
    "```bash\n",
    "$sudo make install\n",
    "```\n",
    "![installcoolprop2linux-make](./img/linux/installcoolprop2linux-make.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!make -f  ./demo/makegslexample.mk"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Reference\n",
    "\n",
    "* [Ubuntu-Python-CPP(Chinese)](https://github.com/PySEE/home/blob/B2021/guide/doc/Ubuntu-Python-CPP(Chinese).md)\n",
    "\n",
    "* [CoolProp Shared Library](http://www.coolprop.org/coolprop/wrappers/SharedLibrary/index.html)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "291px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "widgets": {
   "state": {},
   "version": "1.1.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
